// Poligono1.cpp: implementation of the Poligono class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "sisgraf03.h"
#include "Poligono.h"
#include  <math.h>

using namespace std;

typedef std::list<Puntos> ListaPuntos;

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Poligono::Poligono(ListaPuntos list,int c, bool rellenado)
{
//	Listado = new ListaPuntos(list);
	Listado = list;
	relleno = rellenado;
	color = c;
}

Poligono::~Poligono()
{
//	delete Listado;
}

void Poligono::Transformar(Matriz m)
{
	ListaPuntos::iterator i;
	i = Listado.begin();
	Puntos q = (Puntos)(*i);
	if (!(Listado.empty())) {
		while( i!=(Listado.end()) ) {
			Matriz p1 = Vector(&q);
			double c[2];
			q = Punto(m*p1);
			c[0] = q.obtenerX();
			c[1] = q.obtenerY();
			i->modificarCoord(c);
			i++;
			q = (Puntos)(*i);
		}
	}
}

void Poligono::Dibujar(Matriz m, int *cVP, CDC* pDC)
{
	Transformar(m);
	redondearPtos();

	ListaPuntos ListaClip;
	
	int Xi,Xd,Ya,Yb; //coord del VP
	Xi = *(cVP); //izq
	Xd = *(cVP+1); //der
	Ya = *(cVP+2); //arriba
	Yb = *(cVP+3); //abajo
	
	
	Puntos Pia(Xi,Ya);
	Puntos Pda(Xd,Ya);
	Puntos Pdb(Xd,Yb);
	Puntos Pib(Xi,Yb);

	Recortar(Listado, ListaClip, Pia, Pda);
	Listado = ListaClip;
	ListaClip.clear();
	Recortar(Listado, ListaClip, Pda, Pdb);
	Listado = ListaClip;
	ListaClip.clear();
	Recortar(Listado, ListaClip, Pdb, Pib);
	Listado = ListaClip;
	ListaClip.clear();
	Recortar(Listado, ListaClip, Pib, Pia);
	poligono(color,ListaClip,cVP,relleno,pDC);
}

void Poligono::redondearPtos()
{
	ListaPuntos::iterator i;
	i = Listado.begin();
	Puntos q = (Puntos)(*i);
	if (!(Listado.empty())){
		while( i!=(Listado.end()) ){
			double p[2];
			p[0] = floor (q.obtenerX() + 0.5);
			p[1] = floor (q.obtenerY() + 0.5);	
			q.modificarCoord(p);
			i++;
			q = (Puntos)(*i);
		}
	}
}


void Poligono::Interseccion(Puntos s, Puntos p, Puntos vertice1, Puntos vertice2, Puntos &interseccion)
{
	if (vertice1.obtenerY() == vertice2.obtenerY()) //Limite vertical
	{
		double y = vertice1.obtenerY();
		double x = s.obtenerX() + (vertice1.obtenerY()-s.obtenerY())*
					(p.obtenerX()-s.obtenerX())/(p.obtenerY()-s.obtenerY());
		double c[2];
		c[0] = x;
		c[1] = y;
		interseccion.modificarCoord(c);
	}
	else			//Limite vertical
	{
		double x = vertice1.obtenerX();
		double y = s.obtenerY() + (vertice1.obtenerX()-s.obtenerX()) *
					(p.obtenerY()-s.obtenerY())/(p.obtenerX()-s.obtenerX());
		double c[2];
		c[0] = x;
		c[1] = y;
		interseccion.modificarCoord(c);
	}
}


bool Poligono::Interior(Puntos p, Puntos vertice1, Puntos vertice2)
{
	if (vertice2.obtenerX() > vertice1.obtenerX())	//inferior
		if (p.obtenerY() >= vertice1.obtenerY())
			return TRUE;
	if (vertice2.obtenerX() < vertice1.obtenerX())  //superior
		if (p.obtenerY() <= vertice1.obtenerY())
			return TRUE;
	if (vertice2.obtenerY() > vertice1.obtenerY()) //derecha
		if (p.obtenerX() <= vertice2.obtenerX())
			return TRUE;
	if (vertice2.obtenerY() < vertice1.obtenerY()) //izquierda
		if (p.obtenerX() >= vertice2.obtenerX())
			return TRUE;
	return FALSE;
}


void Poligono::Recortar(ListaPuntos Lista, ListaPuntos &ListaClip, Puntos vertice1, Puntos vertice2)
{

	ListaPuntos::iterator i;
	i = Lista.end();
	i--;
	Puntos s = (Puntos)(*i);
	i = Listado.begin();
	Puntos p = (Puntos)(*i);
	Puntos intersec(0.0,0.0);

	

	while( i!=(Listado.end()) ) 
	{
		p = (Puntos)(*i);
		if (Interior(p,vertice1,vertice2))
		{
			if(Interior(s,vertice1,vertice2))
				ListaClip.push_back(p);
			else
			{
				Interseccion(s,p,vertice1,vertice2,intersec);
				ListaClip.push_back(intersec);
				ListaClip.push_back(p);
			}
		}
		else if (Interior(s,vertice1,vertice2))
			{
				Interseccion(s,p,vertice1,vertice2,intersec);
				ListaClip.push_back(intersec);
			
			}
		
		s = p;
		i++;
	}
}
